package basic.kotlin.function

/**
 * var 与  val 定义变量：
 *      1、var内容可变，可以重新赋值
 *      2、val内容不可变，不可以重新赋值
 *      3、类型推导
 * val修饰的变量相当于java中被final修饰的类型变量--------运行时常量
 * 当被const修饰时，编译器会在编译期间编译为具体的值，否则就是还是对象的引用 ----------编译期常量
 *
 **/
const val FINAL_HELLO_WORLD: String = "HelloWorld"  // 不可以重新赋值

var helloWorld: String = FINAL_HELLO_WORLD          // 可以重新赋值

val FINAL_HELLO_CHINA = "HelloChina"                // 类型推导,由编译器判断。

// 默认返回值 Unit 相当于java中的void，就是什么都不返回，也可省略
fun main(args: Array<String>) { // (Array<String>) -> Unit

//    FINAL_HELLO_WORLD="qqqq"
    helloWorld="123456"   // 对var 修饰的常量进行重新赋值
    println(helloWorld)
    println(FINAL_HELLO_CHINA)

    println("hello ${args[0]}")

    var arrayOfstr: Array<String> = arrayOf("1","3")
    checkArgs(arrayOfstr)
    val arg1 = arrayOfstr[0].toInt()
    val arg2 = arrayOfstr[1].toInt()
    println("$arg1 + $arg2 = ${sum(arg1, arg2)}")

    println(int2Long(3))

    println(sum(1,3))
    println(sum.invoke(1,3))  // invoke是 运算符重载

    arrayOfstr.forEach(::println)  // reference 写法

// 不加ForEach@ 是退出forEach所在的函数，后面的代码不会被执行
// 加ForEach@ 是退出整个for循环，后面的代码依然会被执行
    arrayOfstr.forEach ForEach@{
        if(it == "3") return@ForEach
        println(it)
    }

    println("The End")

    // 函数的最大参数是22个  0-22
    println(sum)
    println(int2Long)
//    println((::printUsage is ()-> Unit))
}

fun checkArgs(args: Array<String>) {
    if (args.size != 2) {
        printUsage()
        System.exit(-1)
    }
}

// 函数定义 --- 无返回值
fun printUsage() {
    println("请传入两个整型参数，例如 1 2") // (Any?) -> Unit
} // ()->Unit

// lambda 表达式  (Int, Int) -> Int
val sum = { arg1: Int, arg2: Int ->
    println("$arg1 + $arg2 = ${arg1 + arg2}")
    arg1 + arg2
}


// ()-> Unit
val printlnHello = {
    println("Hello")
}

// 匿名函数定义  有返回值
val int2Long = fun(x: Int): Long {
    return x.toLong()
}
